//该控件用来管理页面上的所有widget
define(function(require, exports, module) {
    'use strict';

    var me = {};

    var containmentSel = '#crm-panel';
    var widgetSel = '[id][wtype]:not([is-private])';
    var draggableSel = '.xsy_designer_draggable[id][wtype]:not([is-private="true"])';
    var droppableSel = '.xsy_designer_droppable';

    if (seajs.data.dev) {}
    if (window.SESSION.prj === 'canvas') {}

    var _rk;
    var hoveringId, selectId;
    //初始化为编辑模式
    me.beEditMode = function(obj) {
        _rk = obj._rk;
        var mgr = this;
        var that = this;
        $('body').on('hover', '*', function(e) {
            e.stopPropagation();
            var elem = $(this);
            var welem = elem.closest(draggableSel);
            var wid = welem.attr('id');
            hoveringId = wid;
        })
        $('body').on('hover', '*', function(e) {
            e.stopPropagation();
            var target = $(e.target)
            if(target.is('.xsy_drop_indicator') || target.closest('.xsy_drop_indicator').size() > 0)return;
            if(target.is('.xsy_select_cover') || target.closest('.xsy_select_cover').size() > 0)return;
            if(isDragging)return;
            var elem = $(this);
            var welem = elem.closest(draggableSel);
            if (welem.parents('[id][wtype]').size() > 0) {
                var wid = welem.attr('id');
                if (wid) {
                    selectId = wid;
                    _rk.runDesignerMethod('designer.canvas.handleOnSelect', wid);
                }
            } else {
                me.unSelect();
            }
        });
        $('body').on('click', '*', function(e) {
            e.stopPropagation();
            var elem = $(this);
            var welem = elem.closest(draggableSel);
            if (welem.parents('[id][wtype]').size() > 0) {
                var wid = welem.attr('id');
                if (wid) {
                    _rk.runDesignerMethod('designer.canvas.handleOnClick', wid);
                }
            }
        });
        $('#select_cover .delete_btn').click(function(e) {
            that.askDelete(selectId);
        });
        me.listenOutsideDrop();

        window.setInterval(function() {
            if (hoveringId) me.beHover(hoveringId);
            if (selectId) me.beSelect(selectId);
        }, _rk.isIE ? 1 : 10);
    };


    me.doDelete = function(wid) {
        var mgr = _rk.formMgr;
        mgr.deleteWidget(wid);
        me.unHover();
        me.unSelect();
        hoveringId = null
        selectId = null;        
        _rk.runDesignerMethod('designer.editor.close');
    };
    me.askDelete = function(wid) {
        var mgr = this;
        var winfo = mgr.getWidgetInfo(wid);
        _rk.runDesignerMethod('designer.askDelete', {
            widgetType: winfo.widgetType,
            entityId: $('#'+winfo.uuid).attr('entityid'),
            uuid: wid
        });
    };
    me.beHover = function(wid) {return;
        var welem = $('#' + wid);
        if (welem.closest('[wtype]').size() === 0) return; //不可选中最外层的控件
        var w = $('#' + wid);
        var offset = w.offset();
        if (!offset) return;
        $('#hover_cover').show().css({
            left: offset.left,
            top: offset.top,
            width: w.outerWidth(),
            height: w.outerHeight()
        });
    };
    me.unHover = function() {
        $('#hover_cover').hide()
    };
    me.beSelect = function(wid) {
        var mgr = this;
        var welem = $('#' + wid);
        if (!wid) me.unSelect();
        if (welem.closest('[wtype]').size() === 0) return; //不可选中最外层的控件
        var w = $('#' + wid);
        var wtype = w.attr('wtype');
        var offset = w.offset();
        if (!offset) return;

        var transformVal = $('html').css('transform');
        if(_rk.isIE)transformVal = transformVal.split('(')[1];
        var scalelist = transformVal.match(/[\.\d]+/g);
        var scale = _.sortBy(scalelist, function(num){ return parseFloat(num); });
        scale = scale[scale.length-1];//获取到窗口缩放比例，默认为1
        if(_rk.isIE){
            $('#select_cover').show().css({
                left: offset.left - _rk.runDesignerMethod('designer.getIframeScroll').left,
                top: offset.top - _rk.runDesignerMethod('designer.getIframeScroll').top,
                width: w.outerWidth()*scale,
                height: w.outerHeight()*scale
            });
        }else{
            $('#select_cover').show().css({
                left: offset.left/scale,
                top: offset.top/scale,
                width: w.outerWidth(),
                height: w.outerHeight()
            });
        }

        var winfo = {
            uuid: wid,
            widgetType: wtype
        }
        if(me.canDelete(winfo)){
            $('#select_cover').find('.delete_btn').show();
        }else{
            $('#select_cover').find('.delete_btn').hide();
        }
    };
    me.unSelect = function() {
        selectId = null;
        $('#select_cover').hide()
    };
    me.getSelectedId = function() {
        return selectId;
    };

    //iframe内外拖拽的实现
    var isDragging = false;
    var dndinfo, dndinfo2; //缓存，用来解决拖拽到高亮示意框上时丢失拖拽信息的问题

    var inside = {
        before: [0, 50],
        after: [50, 101]
    };

    function vpos(evt, el, sections) {
        //前闭后开区间
        sections = sections || inside;
        if (!el.offset()) return false;
        //当鼠标在容器中滑动时
        if(el.is(droppableSel)){
            if(el.find('>'+draggableSel).size() === 0) {
                return 'in';
            }else{
                //after, before
                var distance = 0,
                    targetId = 0,
                    targetTop = 0,
                    evtY = evt.offsetY,
                    adjustEvtY = evtY - (el.offset().top > 0?0:Math.abs(el.offset().top));
                // console.log("evtY =>" +evtY);
                // console.log("adjustevtY =>" + adjustEvtY);
                //遍历每个孩子，找出鼠标位置最近的一个节点
                el.children().not('.xsy_drop_indicator').each(function(){
                    var childTop = el.offset().top > 0 ? $(this).offset().top - Math.abs(el.offset().top):$(this).offset().top;
                    // console.log($(this).attr('id') + " => " + childTop);
                    if(distance == 0){
                        distance = Math.abs(adjustEvtY - childTop);
                        targetId = $(this).attr('id');
                        targetTop = childTop;
                    }else{
                        if(Math.abs(adjustEvtY - childTop) < distance){
                            distance = Math.abs(adjustEvtY - childTop);
                            targetId = $(this).attr('id');
                            targetTop = childTop;
                        }
                    }
                });
                // console.log(el.offset().top);
                // console.log($(evt.target).offset().top);
                // 如果找出的节点是最后一个节点，并且鼠标位置大于节点top，则after , 否则全部before该最近节点
                if(adjustEvtY  > targetTop && el.children().not('.xsy_drop_indicator').last().attr('id') == targetId){
                    return {
                        act:'after',
                        uuid: targetId
                    }
                }else{
                    return {
                        act:'before',
                        uuid: targetId
                    }
                }
            }
        }
        //当鼠标在控件上滑动时，只需判断before和after
        var elHeight = el.height(),
            elOffsetTop = el.offset().top,
            evtOffsetTop = $(evt.target).offset().top,
            evtOffsetY = evt.offsetY,
            dh = Math.round((evtOffsetY + evtOffsetTop - elOffsetTop) * 100 / elHeight);
        // console.log(
        //     'elHeight', elHeight,
        //     'elOffsetTop', elOffsetTop,
        //     'evtOffsetTop', evtOffsetTop,
        //     'evtOffsetY', evtOffsetY,
        //     'dh', dh
        // );
        var pos = _.findKey(sections, function(ar) {
            return ar[0] <= dh && dh < ar[1];
        });
        return pos;
    }
    me.updateIsDraggingStatus = function(bool){
        isDragging = bool;
    };
    me.listenOutsideDrop = function() {
        var selector = [draggableSel, droppableSel, widgetSel].join(','),
            doc = $(document);
        doc.on('dragover', selector, function(evt) {
            isDragging = true;
            me.unSelect();
            evt.preventDefault();
            evt.stopPropagation();

            if ($(evt.target).hasClass('xsy_drop_indicator')) return; //滑过indicator时不处理，否则会有闪动

            var el = $(this),
                oriEvt = evt.originalEvent,
                act = vpos(oriEvt, el);

            var draggingItemData = JSON.parse(_rk.runDesignerMethod('#westPanel', 'westPanel', 'getDraggingItemData'));

            var layoutname = el.data('layout');
            var pel = el.closest('[id][wtype]');
            var pid = pel.attr('id');
            var ptype = pel.attr('wtype')

            dndinfo2 = {
                el: el,
                oriEvt: oriEvt,
                act: act
            };
            var dragInfo = {
                widgetType: draggingItemData.wtype,
                entityId: draggingItemData.winfo.childEntityId
            };
            // var targetInfo = {
            //     uuid: pid,
            //     widgetType: pel.attr('wtype'),
            //     entityId: pel.attr('entityid'),
            //     layoutname: layoutname
            // };
            var targetInfo;
            if(typeof act === 'object'){
                var obj = act;                
                act = obj.act;
                var uuid = obj.uuid;
                el = $('#'+uuid);
                targetInfo = {
                    uuid: uuid,
                    widgetType: el.attr('wtype'),
                    entityId: el.attr('entityid'),
                    layoutname: null
                };
            }else{
                targetInfo = {
                    uuid: pid,
                    widgetType: pel.attr('wtype'),
                    entityId: pel.attr('entityid'),
                    layoutname: layoutname
                };
            }
            var canDrop = me.canDrop(dragInfo, act, targetInfo);
            if(canDrop)
            if (act === 'in') {
                _rk.formMgr.showIndicator(act, pid, layoutname);
            } else {
                _rk.formMgr.showIndicator(act, el.attr('id'));
            }
        });

        doc.on('drop', selector, function(evt) {
            isDragging = false;
            evt.preventDefault();
            evt.stopPropagation();
            var el = $(this),
                oriEvt = evt.originalEvent,
                act = vpos(oriEvt, el),
                data = JSON.parse(decodeURIComponent(oriEvt.dataTransfer.getData('text')));

                console.log(data);

            if ($(evt.target).hasClass('xsy_drop_indicator')) { //在indicator上松开的鼠标
                if (!dndinfo2) return;
                el = dndinfo2.el;
                act = dndinfo2.act;
            }
            var winfo = data.winfo;
            var childEntityId = winfo.childEntityId;//customize的控件，需有entityid
            var isExist = false, wid, searchEl;
            if(childEntityId){
                searchEl = $('#crm-panel').find('[wtype="'+winfo.widgetType+'"][entityid="'+childEntityId+'"]');                
            }else{
                searchEl = $('#crm-panel').find('[wtype="'+winfo.widgetType+'"]');
            }
            if(searchEl.size() > 0) {
                wid = searchEl.attr('id');
                isExist = true;//注意，必须在dom里找，不能在json里找。因为很可能json中存在，但dom中不可见因而未初始化。
            }
            var layoutname = el.data('layout');
            var pel = el.closest('[id][wtype]');
            var pid = pel.attr('id');
            var doAdd = false;//add or move
            if(!isExist || (isExist && winfo._designer_maximumInstanceCount < 0)){
                doAdd = true;
            }
            var dragInfo = {
                widgetType: winfo.widgetType,
                entityId: childEntityId
            };
            var targetInfo;
            if(typeof act === 'object'){
                var obj = act;                
                act = obj.act;
                pid = obj.uuid;
                pel = $('#' + pid);
                layoutname = null;
                targetInfo = {
                    uuid: obj.uuid,
                    widgetType: pel.attr('wtype'),
                    entityId: pel.attr('entityid'),
                    layoutname: layoutname
                };
            }else{
                targetInfo = {
                    uuid: pid,
                    widgetType: pel.attr('wtype'),
                    entityId: pel.attr('entityid'),
                    layoutname: layoutname
                };
            }
            // var targetInfo = {
            //     uuid: pid,
            //     widgetType: pel.attr('wtype'),
            //     entityId: pel.attr('entityid'),
            //     layoutname: layoutname
            // };
            var canDrop = me.canDrop(dragInfo, act, targetInfo);
            if(canDrop)
            if (act === 'in') {
                doAdd ? _rk.formMgr.addWidget(winfo, act, pid, layoutname) :
                        _rk.formMgr.moveWidget(wid, act, pid, layoutname)
            } else {
                doAdd ? _rk.formMgr.addWidget(winfo, act, pid, layoutname) :
                        _rk.formMgr.moveWidget(wid, act, pid, layoutname);
            }
            $('#drop_indicator').remove();
            dndinfo2 = null;
            me.afterDnd();
        });
    };

    var draggingHelper;
    me.hideDndHelper = function(){
        if(!draggingHelper)return;
        $(draggingHelper).hide();
        $('body').trigger('mouseup')
        draggingHelper=null;
    };
    me.beforeDnd = function(){
        $('[wtype="xsyReferContainer"]').css({
            'marginTop': '20px',
            'marginBottom': '20px',
            //'marginBottom': '40px',
            //'border': '1px solid red'
        });
    };
    me.afterDnd = function(){
        $('[wtype="xsyReferContainer"]').css({
            'marginTop': '',
            'marginBottom': '',
            //'border': 0
        });
    };
    me.beEditingDragDrop = function() {
        var mgr = this;
        $(draggableSel).draggable({
            delay: 300,
            cursor: 'move',
            opacity: 0.65,
            addClasses: false,
            revert: true,
            revertDuration: false,
            containment: $(containmentSel),
            helper: 'clone',
            appendTo: containmentSel,
            zIndex: 9999999999999,
            refreshPositions: true,
            start: function(e, ui) {
                me.unSelect();
                me.beforeDnd();
                draggingHelper = $(ui.helper)
                draggingHelper.css({
                    'z-index': '999999999999999',
                    'background-color': 'white',
                    'border': '1px dotted blue',
                    'width': $(e.target).width(),
                    'pointer-events': 'none',
                    left: 0
                });
            },
            stop: function(e, ui) {
                isDragging = false;
                if(_rk.isFirefox && !e.toElement)e.toElement = e.originalEvent.target;
                if ($(e.toElement).hasClass('xsy_drop_indicator') || (_rk.isIE && !e.toElement)/*IE的toElement为空*/) {
                    if (!dndinfo) return;
                    e = dndinfo.e;
                    ui = dndinfo.ui;
                }
                handleDnd('stop', e, ui, function(obj) {
                    _rk.formMgr.moveWidget(obj.widgetId, obj.act, obj.pid, obj.layoutname);
                }, function(obj) {
                    _rk.formMgr.moveWidget(obj.widgetId, obj.act, obj.targetId);
                });
                dndinfo = null;
                me.afterDnd();
            },
            'drag': function(e, ui) {
                if(_rk.isFirefox && !e.toElement)e.toElement = e.originalEvent.target;
                isDragging = true;
                if ($(e.toElement).hasClass('xsy_drop_indicator')) return;
                dndinfo = {
                    e: e,
                    ui: ui
                };
                handleDnd('drag', e, ui, function(obj) {
                    _rk.formMgr.showIndicator(obj.act, obj.pid, obj.layoutname);
                }, function(obj) {
                    _rk.formMgr.showIndicator(obj.act, obj.targetId);
                });
            }
        });
        var handleDnd = function(ename, e, ui, callbackofIn /*in*/ , callbackofAFBF /*after, before*/ ) {
            me.unSelect();
            $('#drop_indicator').remove();

            var oriEvt = e.originalEvent;
            var widget = $(e.target);
            var widgetId = widget.attr('id');
            var widgetType = widget.attr('wtype');
            var widgetEntityId = widget.attr('entityid');
            var toElement = $(e.toElement);

            if (!toElement.is(droppableSel)) toElement = $(toElement).is(widgetSel) ? $(toElement) : $(toElement).closest(widgetSel);
            var pos = vpos(oriEvt, toElement);
            if (pos === false) return;
            var act = pos; //before,after,in
            //console.log(act, targetId)
            if (act !== 'in') {
                if(typeof act === 'object'){
                    var obj = act;                
                    act = obj.act;
                    var uuid = obj.uuid;
                    toElement = $('#'+uuid);
                };
                var targetId = toElement.attr('id');
                var targetType = toElement.attr('wtype');
                var targetEntityId = toElement.attr('entityid');
                var dragInfo = {
                    uuid: widgetId,
                    widgetType: widgetType,
                    entityId: widgetEntityId
                };
                var targetInfo = {
                    uuid: targetId,
                    widgetType: targetType,
                    entityId: targetEntityId
                };
                var canDrop = me.canDrop(dragInfo, act, targetInfo);
                if(canDrop)
                if (widgetId !== targetId && $('#' + targetId).parents('[id="' + widgetId + '"]').size() === 0) {
                    (callbackofAFBF)({
                        widgetId: widgetId,
                        act: act,
                        targetId: targetId
                    });
                }
            } else {
                var layoutname = toElement.data('layout');
                var pel = toElement.closest('[id][wtype]');
                var pid = pel.attr('id');
                var ptype = pel.attr('wtype');
                var pEntityId = pel.attr('entityid');
                var dragInfo = {
                    uuid: widgetId,
                    widgetType: widgetType,
                    entityId: widgetEntityId
                };
                var targetInfo = {
                    uuid: pid,
                    widgetType: ptype,
                    entityId: pEntityId,
                    layoutname: layoutname
                };
                var canDrop = me.canDrop(dragInfo, act, targetInfo);
                if(canDrop)
                (callbackofIn)({
                    widgetId: widgetId,
                    act: act,
                    pid: pid,
                    layoutname: layoutname
                });
            }
        };
    };
    me.cleanDndIndicator = function(){
        $('#drop_indicator').remove();
    };
    //拖拽规则判断
    var allWestItems;
    var loadWestList = function(){
        var allitems = _rk.runDesignerMethod('#westPanel', 'westPanel', 'getAllItems');
        allWestItems = {};
        for(var key in allitems){
            var item = allitems[key];
            if(item.designerConfig && item.designerConfig.hideFlg !== 1){
                allWestItems[key] = item;
            }
        }
    };
    me.canDrag = function(wtype, entityId) {
        if(!allWestItems) loadWestList();
        if(!_rk.runDesignerMethod('designer.catagory.canDrag', wtype, entityId)) return false;
        if((/^(xsy)[\w]+(Detail)$/g).test(wtype)) return false;//详情页本身不能拖拽
        for(var key in allWestItems){
            var arr = key.split(',');
            var itype = arr[0];
            var ientity = arr[1];
            //console.log('   ?', itype, wtype)
            if(itype === wtype){
                if(ientity && (ientity+'') === (entityId)+'') return true;
                if(!ientity && !entityId) return true;
            }
        }
        return false;
    };
    me.canDrop = function(dragInfo, act, targetInfo) {
        // head不能删
        // head旁边不能拖入组件
        // 卡片只能和卡片放在一起
        // tab不能嵌套tab
        // 资料不能删
        // 容器中若有东西，不能删
        // tab中，只有所有tab中的控件都删光，才可以删除tab
        if((/(Header)$/g).test(targetInfo.widgetType)) return false;//head旁边什么都不能放
        if((/^(xsy)[\w]+(Detail)$/g).test(targetInfo.widgetType)) return false;//详情页本身不能拖拽
        //卡片控件只能放在卡片容器中
        var pid = _rk.formMgr.getWidgetInfo(targetInfo.uuid).pid;
        var pinfo = _rk.formMgr.getWidgetInfo(pid);
        var pid_drag = dragInfo.uuid ? _rk.formMgr.getWidgetInfo(dragInfo.uuid).pid : null;
        var pinfo_drag = pid_drag ? _rk.formMgr.getWidgetInfo(pid_drag) : pid_drag;
        if(act==='in'){
            if(targetInfo.widgetType==='xsyReferContainer' && !(/(Refer)$/g).test(dragInfo.widgetType)) return false;
            if(targetInfo.widgetType === 'xsyHorizontalLayout' && targetInfo.layoutname === 'list'){
                return false;
            }
        }else{
            if(!(/(Refer)$/g).test(dragInfo.widgetType) && (/(Refer)$/g).test(targetInfo.widgetType)){
                if(pinfo.widgetType === 'xsyReferContainer') return false;
            }else 
            if((/(Refer)$/g).test(dragInfo.widgetType) && (/(ReferContainer)$/g).test(targetInfo.widgetType)){
                return false;
            }else
            if((/(Refer)$/g).test(dragInfo.widgetType) && !(/(Refer)$/g).test(targetInfo.widgetType)){
                var livingList = _rk.formMgr.getLivingChildrenList(targetInfo.uuid);
                if(pid != pid_drag)//不同容器之间拖拽卡片时，如果里面已经存在卡片了，则必须挨着卡片放（磁石效应）
                if($.isArray(livingList)){
                    for(var i=0,len=livingList.length;i<len;i++){
                        if((/(Refer)$|(ReferContainer)$/g).test(livingList[i].widgetType)){                    
                            return false;
                        }
                    }
                }
            }
            if(targetInfo.widgetType === 'xsyHorizontalLayout'){
                return false;//暂时不允许在horizontal上下放孩子
            }
            if(targetInfo.widgetType === 'xsyOpportunityProgress'){
                return false;//暂时不允许在其上下放孩子
            }
        }
        if(dragInfo.widgetType === 'xsyTab'){
            var grandTabs = $('#' + targetInfo.uuid).parents('[wtype="xsyTab"]');
            if(grandTabs.size()>0)return false;//tab里不能放tab
        }
        var westItem = _rk.runDesignerMethod('#westPanel', 'westPanel', 'getItemInfo', dragInfo.widgetType);
        // console.log(
        //     'candrop?',
        //     JSON.stringify(dragInfo),
        //     act, 
        //     JSON.stringify(targetInfo),
        //     westItem
        //     );
        if(!allWestItems) loadWestList();
        if(westItem._designer_maximumInstanceCount !== -1){
            if(dragInfo.widgetType === targetInfo.widgetType)
             if(dragInfo.entityId || targetInfo.entityId){
               if((dragInfo.entityId+'') === (targetInfo.entityId+''))
                return false;
             }else{
                return false;
             }
        }
        if(dragInfo.entityId && ((dragInfo.entityId+'') === (targetInfo.entityId+''))) return false;
        return true;
    };
    me.canDelete = function(info) {
        if(!allWestItems) loadWestList();
        if((/(Info)$/g).test(info.widgetType)) return false;
        if(info.widgetType === 'xsyTab'){
            var winfo = _rk.formMgr.getWidgetInfo(info.uuid);
            if(winfo.children && winfo.children.length > 0){
                for(var i=0,len=winfo.children.length;i<len;i++){
                    var child = winfo.children[i];
                    var childinfo = _rk.formMgr.getWidgetInfo(child.uuid);
                    if(childinfo.children && childinfo.children.length > 0){
                        return false;
                    }
                }
            }
        }
        return true;
    };


    module.exports = me;
});
